package p.ithorns.tools.validation;


import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * IdCardValidator
 * <p>
 * 身份证校验
 *
 * @author liuhaitao
 * @version 1.0.0
 * @date 2022/5/5 14:23
 */
public class IdCardValidator implements ConstraintValidator<IdCard, CharSequence> {

    // private final static Logger log = LoggerFactory.getLogger(IdCardValidator.class);

    // 身份证系数
    private final static int[] COEFFICIENT_ARR = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};

    // 余数数组
    private final static int[] REMAINDER_ARR = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // 身份证号码第18位数组
    private final static int[] LAST_ARR = {1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2};

    @Override
    public boolean isValid(CharSequence charSequence, ConstraintValidatorContext context) {
        String idCard = charSequence.toString();
        if (StringUtil.isBlank(idCard)) {
            return false;
        }

        if (idCard.length() != 18) {
            return false;
        }

        try {
            // 1.将身份证号码前面的17位数分别乘以不同的系数。
            int sum = 0;
            for (int i = 0; i < COEFFICIENT_ARR.length; i++) {
                // Character.digit 在指定的基数返回字符ch的数值。
                // 如果基数是不在范围内MIN_RADIX≤基数≤MAX_RADIX或如果该值的通道是不是一个有效的数字在指定的基数-1，则返回。
                // ch - the character to be converted(要转换的字符)
                // ch - int类型，是字符的ASCII码，数字的ASCII码是48-57
                // radix - the radix(基数) ----也就是进制数
                sum += Character.digit(idCard.charAt(i), 10) * COEFFICIENT_ARR[i];
            }

            String matchDigit = "";
            for (int i = 0; i < REMAINDER_ARR.length; i++) {
                int j = REMAINDER_ARR[i];
                if (j == sum % 11) {
                    matchDigit = String.valueOf(LAST_ARR[i]);
                    if (LAST_ARR[i] > 57) {
                        matchDigit = String.valueOf((char) LAST_ARR[i]);
                    }
                }
            }
            if (matchDigit.equals(idCard.substring(idCard.length() - 1))) {
                return true;
            }
        } catch (Exception e) {
            System.err.printf("校验身份证出现异常%s%n", e);
        }

        return false;
    }

}